package main

/*
#cgo  CFLAGS:  -I  ./include
#cgo  LDFLAGS:  -L ./lib  -l2048
#include "2048.h"
*/
import "C"

import (
	"2048-ai/HttpServer/ai"
	"2048-ai/HttpServer/grid"
	"errors"
	"fmt"
	"github.com/gin-gonic/gin"
	"strconv"
	"strings"
	"unsafe"
)

func main() {
	C.init_tables()
	router := gin.Default()
	router.POST("/2048ai/v1", ai2048)
	router.POST("/2048ai/v2", New_ai2048)
	router.Run(":8888")
}
func ai2048(c *gin.Context) {
	gird := c.PostForm("gird")
	girdlen := c.PostForm("len")
	result := DealGird(gird, girdlen)
	c.JSON(200, gin.H{
		"direction": result,
	})
}

func New_ai2048(c *gin.Context) {
	gird := c.PostForm("gird")
	girdlen := c.PostForm("len")
	result := NewDealGird(gird, girdlen)
	fmt.Printf("direction:%d\n",result)
	c.JSON(200, gin.H{
		"direction": result,
	})
}

func NewDealGird(gird string, girdlen string) int {
	Num, err := strconv.Atoi(girdlen)
	if err != nil {
		return -1
	}
	//fmt.Println(gird)
	Data, err := StringToCint(gird, Num)
	if err != nil {
		return -1
	}
	fmt.Println(Data)

	inPointer := unsafe.Pointer(&Data[0])
	inC := (*C.int)(inPointer)
	result := int(C.AI_2048(inC, 16))
	switch result {
	case 0:
		return 0
	case 1:
		return 2
	case 2:
		return 3
	case 3:
		return 1
	}
	return result
}

func DealGird(gird string, girdlen string) int {
	g := &grid.Grid{}
	Num, err := strconv.Atoi(girdlen)
	if err != nil {
		return -1
	}
	Data, err := StringToGird(gird, Num)
	if err != nil {
		return -1
	}
	SendErWei(Data, Num)
	g.Data = Data
	a := &ai.AI{Grid: g}
	dire := a.Search()
	return int(dire)
}

func StringToGird(gird string, Num int) ([4][4]int, error) {
	var result [4][4]int
	datas := strings.Split(gird, "*")
	if Num > 4 {
		return result, errors.New("超出范围")
	}

	for a := 0; a < len(datas); a++ {
		k := strings.Split(datas[a], "#")
		for b := 0; b < len(k); b++ {
			num, err := strconv.Atoi(k[b])
			if err != nil {
				return result, err
			}
			result[a][b] = num
		}
	}
	return result, nil
}

func SendErWei(data [4][4]int, num int) {
	for a := 0; a < num; a++ {
		for b := 0; b < num; b++ {
			fmt.Printf("%-5d", data[a][b])
		}
		fmt.Println()
	}
}

func StringToCint(gird string, Num int) ([16]C.int, error) {
	var result [16]C.int
	datas := strings.Split(gird, "*")
	if Num > 4 {
		return result, errors.New("超出范围")
	}

	for a := 0; a < len(datas); a++ {
		k := strings.Split(datas[a], "#")
		for b := 0; b < len(k); b++ {
			num, err := strconv.Atoi(k[b])
			if err != nil {
				return result, err
			}
			result[a*4+b] = C.int(num)
		}
	}
	return result, nil
}
